package  {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.MovieClip;
    import flash.events.*;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.text.TextField;
    import flash.utils.Timer;
    import Planet;
        
    public class SuperStar extends MovieClip {
        {//member variables
        public var objects :Array = new Array();//all the objects on screen
        public var esv:Planet;//the EVIL SPACE VOID ME HUNGRY
        public var safeZone:StarSafeZone;
        private var blackHoleRadius:int = 65;//size of the void
        private var starRadius:int = 15;//size of the stars
        private var numInitialStars:int = 1;//number of stars on screen when the game starts
        private var timeBetweenStarSpawns:int = 1000; //higher = stars spawn less frequently (in ms)
        private var addStarTimer:Timer = new Timer(timeBetweenStarSpawns, 0);
        public var shrinkButton:ShrinkRayButton;
        public var freezeButton:FreezeRayButton;
        public var shieldButton:ShieldRayButton;
        public var safeStars:Array = new Array();//all the stars which are currently safe
        public var safeFreezePowerups:Array = new Array(); //all the freeze powerups which are currently safe
        public var safeShieldPowerups:Array = new Array();//all the shield powerups

        public var winning:Boolean = false; //true if the player shrinks the void to zero
        public var losing:Boolean = false;//true if the void expands to the edges of the screen
        private var scoreText:TextField = new TextField();
        public var score:int = 0; 
        private var scoreTimer:Timer = new Timer(5000, 0);
        private var bmp:Bitmap;
                
        private var esvImage:Loader = new Loader();
        private var starImage:Loader = new Loader();
        }
                
        public function SuperStar()
        {
            //listen for win or lose conditions
            this.addEventListener(Event.ENTER_FRAME, iCanHazWon);
            
            //increment the score over time
            scoreTimer.addEventListener(TimerEvent.TIMER, incrementScore);
            scoreTimer.start();
            
            //load the background image before anything else
            var backgroundurl:String = "images/sky.png";
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            loader.load(new URLRequest(backgroundurl));     
        }

        //display the loaded image
        private function completeHandler(e:Event):void {
            addChild(Loader(e.target.loader));
            addObjects();//make some stuff and tell it to do things
        }
		
        //output an error if the image cannot be loaded
        private function ioErrorHandler(e:Event):void {
            var loader:Loader = Loader(e.target.loader);
            trace("Unable to load image: " + loader.contentLoaderInfo.url);
        }
                
        //I Can Haz Cheezburger?
        private function iCanHazWon(e:Event) {
            if (winning) {
				MovieClip(esvImage.content).stop();
                addStarTimer.stop();
                scoreTimer.stop();
                incrementScore(null, 2000);
                freezeButton.removeEventListener(MouseEvent.CLICK, fireFreezeRay);
                shieldButton.removeEventListener(MouseEvent.CLICK, fireShieldRay);
                shrinkButton.removeEventListener(MouseEvent.CLICK, fireShrinkRay);
                trace("Yay, you won, you must be good and stuff.");
                this.removeEventListener(Event.ENTER_FRAME, iCanHazWon);
                for (var i = 0; i < objects.length; i++) {
                    objects[i].removeEventListener(MouseEvent.MOUSE_DOWN, objects[i].drag);
                    objects[i].immune = true;
                    objects[i].velX = 0;
                    objects[i].velY = 0;
                }

                var winText:TextField = new TextField();
                winText.text = "YOU WON!";
                winText.textColor = 0xFFFFFF;
                var textBmapData:BitmapData = new BitmapData(100,25,true,0x00000000);
                textBmapData.draw(winText);
                var textbmp:Bitmap = new Bitmap(textBmapData);
                textbmp.x = stage.stageWidth / 2 - textbmp.width / 2;
                textbmp.y = stage.stageHeight / 2 - textbmp.height / 2;
                this.addChild(textbmp);
				
                } else if(losing) {
                    trace("You're not very good at this stuff, maybe you should try knitting?");
					MovieClip(esvImage.content).stop();
                    addStarTimer.stop();
                    scoreTimer.stop();
                    //incrementScore(null, -1000);
                    freezeButton.removeEventListener(MouseEvent.CLICK, fireFreezeRay);
                    shieldButton.removeEventListener(MouseEvent.CLICK, fireShieldRay);
                    shrinkButton.removeEventListener(MouseEvent.CLICK, fireShrinkRay);
                    this.removeEventListener(Event.ENTER_FRAME, iCanHazWon);
                    for (var i = 0; i < objects.length; i++) {
                        objects[i].removeEventListener(MouseEvent.MOUSE_DOWN, objects[i].drag);
                        objects[i].immune = true;
                        objects[i].velX = 0;
                        objects[i].velY = 0;
                    }
                    
                    var loseText:TextField = new TextField();
                    loseText.text = "YOU LOST!";
                    loseText.textColor = 0xFFFFFF;
                    var textBmapData:BitmapData = new BitmapData(100,25,true,0x00000000);
                    textBmapData.draw(loseText);
                    var textbmp:Bitmap = new Bitmap(textBmapData);
                    textbmp.x = stage.stageWidth / 2 - textbmp.width / 2;
                    textbmp.y = stage.stageHeight / 2 - textbmp.height / 2;
                    this.addChild(textbmp);
                }
                        
        }
                
        //if you don't know what this function does after looking at the name then I just don't know
        private function addObjects() {
            shrinkButton = new ShrinkRayButton(this);//create the shrink ray button, but don't make it visible until it can be used
            shrinkButton.x = stage.stageWidth - 10;
            shrinkButton.y = shrinkButton.height + 10;
                        
            freezeButton = new FreezeRayButton(this);
            freezeButton.x = shrinkButton.x;
            freezeButton.y = shrinkButton.y + freezeButton.height;
                        
            shieldButton = new ShieldRayButton(this);
            shieldButton.x = shrinkButton.x - 2 * shieldButton.width;
            shieldButton.y = 3;
                        
            safeZone = new StarSafeZone();
            safeZone.height = safeZone.width;
            safeZone.height *= 0.8;
            safeZone.width *= 0.8;
            safeZone.x = stage.stageWidth;
            safeZone.y = stage.stageHeight;
            this.addChild(safeZone);//create the safe zone
                        
            //add a score display
            scoreText.text = "Score = " + score;
            scoreText.textColor = 0xFFFFFF;
            var scoreBmapData:BitmapData = new BitmapData(80,20,true,0x00000000);
            scoreBmapData.draw(scoreText);
            bmp = new Bitmap(scoreBmapData);
            bmp.x = stage.stageWidth / 2 - bmp.width / 2;
            bmp.y = stage.stageHeight - bmp.height - 5;
            this.addChild(bmp);
                        
            //load the image displayed for the ESV
            esvImage.contentLoaderInfo.addEventListener(Event.COMPLETE, createESV);
            esvImage.load(new URLRequest("images/vortex.swf"));
                        
            //load the image for the regular stars
            starImage.contentLoaderInfo.addEventListener(Event.COMPLETE, addInitialStars);
            starImage.load(new URLRequest("images/star.png"));

        }
                
        private function addInitialStars(e:Event) {
            for (var i = 0; i < numInitialStars; i++) {
                addStar(null);
            }
                        
            //continue to add more stars over time
            addStarTimer.addEventListener(TimerEvent.TIMER, addStar);
            addStarTimer.start();
        }
                
        // Create EVIL SPACE VOIIIIIID ooooo scary
        private function createESV(e:Event) {
            esv = new Planet(blackHoleRadius, true, this, esvImage);
            //trace("ESV Radius = " + esv.radius);
            esv.immune = true;//the void shouldn't pull on itself that would be weird and kinda crazy
            esv.y = stage.stageHeight / 2;
            esv.x = esv.y;
            objects.push(esv);
            this.addChild(esv);//show it on screen
        }
                
                
        //increment the score and update the screen display
        public function incrementScore(e:Event, add:int = 50) {
            score += add;
            
			this.removeChild(bmp);
            scoreText.text = "Score = " + score;
            scoreText.textColor = 0xFFFFFF;
            var scoreBmapData:BitmapData = new BitmapData(80,20,true,0x00000000);
            scoreBmapData.draw(scoreText);
            bmp = new Bitmap(scoreBmapData);
            bmp.x = stage.stageWidth / 2 - bmp.width / 2;
            bmp.y = stage.stageHeight - bmp.height - 5;
            this.addChild(bmp);
        }
                
        //Freezes time for freezeLength number of seconds
        public function fireFreezeRay(e:Event) {
            var freezeLength:int = 3000;
                        
            this.removeChild(safeFreezePowerups.pop());
                        
            freezeButton.removeEventListener(MouseEvent.CLICK, fireFreezeRay);
                        
            if (safeFreezePowerups.length == 0) this.removeChild(freezeButton);
                        
            var freezeTimer:Timer = new Timer(freezeLength, 1);
            addStarTimer.stop();
            var xVels:Array = new Array();
            var yVels:Array = new Array();

                        
            for (var i = 0; i < objects.length; i++) {
                objects[i].immune = true;
                xVels.push(objects[i].velX);
                yVels.push(objects[i].velY);
                objects[i].velX = 0;
                objects[i].velY = 0;
                objects[i].isFrozen = true;
            }
            freezeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, function(e:Event):void {
                unfreeze(e, freezeTimer, xVels, yVels);
            });
            freezeTimer.start();
                        
            incrementScore(null, 150);
						
			MovieClip(esvImage.content).stop();
        }
                
        //Unfreeze Time
        private function unfreeze(e:Event, freezeTimer, xVels, yVels) {
            freezeTimer.stop();
            addStarTimer.start();
                        
            freezeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, function(e:Event):void {
                unfreeze(e, freezeTimer, xVels, yVels);
            });
                        
            for (var i = objects.length - 1; i >= 0; i--) {
                if(!objects[i].isBeingDragged) {
                    objects[i].immune = false;
                    objects[i].velX = xVels.pop();
                    objects[i].velY = yVels.pop();
                }
                objects[i].isFrozen = false;
            }
            esv.immune = true;
                        
            freezeButton.addEventListener(MouseEvent.CLICK, this.fireFreezeRay);
						
			MovieClip(esvImage.content).play();
        }
                
        //if the shrink ray is fired, decrease the radius of the void according to how many stars are in the safe zone
        //also, remove the safe stars from the safe zone
        public function fireShrinkRay(e:Event) {
            var numStars = safeStars.length;
            if (safeZone.hasAlien) safeZone.hasAlien = false;
            safeZone.alien = null;
                        
            esv.decreaseRadius(numStars);
                        
            for (var i = 0; i < numStars; i++) {
                this.removeChild(safeStars[i]);
            }
            safeStars = new Array();
            this.removeChild(shrinkButton);
                        
            //shrink the safe zone by 10% each time.... unless it will be too small to fit a star inside
            if(safeZone.width * 0.9 >= 2 * starRadius) {
                safeZone.width *= 0.9;
                safeZone.height *= 0.9;
            }
                        
            //since the safe zone is smaller, make sure all the freeze powerups are still inside it
            if (safeFreezePowerups.length != 0) {
                for (var i = 0; i < safeFreezePowerups.length; i++) {
                    if (!safeZone.isInSafeZone(safeFreezePowerups[i])) {
                        safeFreezePowerups[i].x = safeZone.x - safeFreezePowerups[i].radius;
                        safeFreezePowerups[i].y = safeZone.y - safeFreezePowerups[i].radius;
                    }
                }
            }
                        
            //same as above for shield powerups
            if (safeShieldPowerups.length != 0) {
                for (var i = 0; i < safeShieldPowerups.length; i++) {
                    if (!safeZone.isInSafeZone(safeShieldPowerups[i])) {
                        safeShieldPowerups[i].x = safeZone.x - safeShieldPowerups[i].radius;
                        safeShieldPowerups[i].y = safeZone.y - safeShieldPowerups[i].radius;
                    }
                }
            }
                        
                        
            //increment the score depending on how many stars were inside the safe zone
            if (numStars <= 3) incrementScore(null, numStars * 15);
            else if (numStars <= 5) incrementScore(null, numStars * 20);
            else if (numStars <= 7) incrementScore(null, numStars * 25);
            else incrementScore(null, numStars * 30);
        }
                
        //while the shield is active, stars will bounce off of the void instead of falling in
        public function fireShieldRay(e:Event) {
            var shieldRayTimer:Timer = new Timer(6000, 1);
            shieldRayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, removeShield);
                        
            this.removeChild(safeShieldPowerups.pop());
                        
            shieldButton.removeEventListener(MouseEvent.CLICK, fireShieldRay);
            if (safeShieldPowerups.length == 0) this.removeChild(shieldButton);
                        
                        
            esv.isShieldOn = true;
                        
            shieldRayTimer.start();
                        
            incrementScore(null, 150);
        }
                
        //the void will now eat stars again
        private function removeShield(e:Event) {
            esv.isShieldOn = false;
                        
            shieldButton.addEventListener(MouseEvent.CLICK, fireShieldRay);
        }
                
        //make a star and add it to the screen
        //NOTE: stars are created off-screen and then drift towards the void so they're not just poppin up anywhere that wouldn't make much sense now would it
        private function addStar(e:Event) {
            var p :Planet = new Planet(starRadius, false, this);
            p.addEventListener(MouseEvent.MOUSE_DOWN, p.drag);//listen if the player drags this guy with the mouse
                        
            p.y = randomNumber( -200, stage.stageHeight + 200);//generate a y-position
            while ((p.y >= -p.radius) && (p.y <= stage.stageHeight + p.radius)) {//make sure its not on screen
                p.y = randomNumber ( -200, stage.stageHeight + 200);
            }

            p.x = randomNumber(stage.stageHeight / 2, stage.stageWidth + 50);//randomly generate an x position, always to the right of the ESV

            p.velY = randomNumber( -5, 5);//give it an initial push to get things going
            objects.push(p);//add it to the list of objects
            this.addChild(p);//display it on screen
        }
                
        //generate a random number between low and high
        //useful for randomly placing things on screen
        public function randomNumber(low:int, high:int):int {
            return Math.floor(Math.random() * (1 + high - low)) + low;
        }
                
    }
}